package com.icez.ball_ripple_progress_library

import android.animation.*
import android.view.View
import androidx.core.animation.addListener

/**
 *  动画工具类
 *  插值器：
 * 1：AccelerateDecelerateInterpolator 加速减速插补器（先慢后快再慢）
 * 2：AccelerateInterpolator 加速插补器（先慢后快）
 * 3：AnticipateInterpolator 向前插补器（先往回跑一点，再加速向前跑）
 * 4：AnticipateOvershootInterpolator 向前向后插补器（先往回跑一点，再向后跑一点，再回到终点）
 * 5：BounceInterpolator 反弹插补器（在动画结束的时候回弹几下，如果是竖直向下运动的话，就是玻璃球下掉弹几下的效果）
 * 6：CycleInterpolator 循环插补器（按指定的路径以指定时间（或者是偏移量）的1/4、变速地执行一遍，再按指定的轨迹的相反反向走1/2的时间，再按指定的路径方向走完剩余的1/4的时间，最后回到原点。假如：默认是让a从原点往东跑100米。它会先往东跑100米，然后往西跑200米，再往东跑100米回到原点。可在代码中指定循环的次数）
 * 7：DecelerateInterpolator 减速插补器（先快后慢）
 * 8：LinearInterpolator 直线插补器（匀速）
 * 9：OvershootInterpolator 超出插补器（向前跑直到越界一点后，再往回跑）
 * 10：FastOutLinearInInterpolator MaterialDesign基于贝塞尔曲线的插补器 效果：依次 慢慢快
 * 11：FastOutSlowInInterpolator MaterialDesign基于贝塞尔曲线的插补器 效果：依次 慢快慢
 * 12：LinearOutSlowInInterpolator MaterialDesign基于贝塞尔曲线的插补器 效果：依次 快慢慢
 *  估值器：
 *          BezierEvaluator  贝塞尔算法
 *          ArgbEvaluator() 可用于颜色渐变设置
 *
 *
 * @author icez
 */
class AnimatorUtil {
    companion object{
        val instance:AnimatorUtil by lazy(mode=LazyThreadSafetyMode.SYNCHRONIZED){
            AnimatorUtil()
        }
    }


    /**
     *  objectAnimator动画
     * @param view 动画控件
     * @param type 动画类型
     * @param mOnObjectAnimatorAttributeListener 属性设置
     * @param mAddUpdateListener 动画监听
     * @param values 动画参数
     * @param animXmlResId 动画xml id
     * @param customProperty 自定义调用指定的方法，例如：值为name，那么动画会调用setName(value:Float)方法，所以您要在控件中自定义一个setName(value:Float)方法
     * @return 动画对象
     */
    public fun objectAnimator(
        view: View?,
        type:ObjectAnimatorType?,
        animXmlResId:Int?,
        customProperty:String?,
        mOnObjectAnimatorAttributeListener: ((objectAnimator: ObjectAnimator) -> Unit)?,
        mAddUpdateListener: ((valueAnimator: ValueAnimator) -> Unit)?,
        vararg values: Float
    ): ObjectAnimator? {
        var objectAnimator:ObjectAnimator ?= null
        when(type){
            ObjectAnimatorType.ROTATION -> {
                if(values.isEmpty()){
                    throw Exception("values不能为null")
                }
                objectAnimator = ObjectAnimator.ofFloat(view,View.ROTATION,*values)//"rotation"  它会调用setRotation
            }
            ObjectAnimatorType.ALPHA -> {
                if(values.isEmpty()){
                    throw Exception("values不能为null")
                }
                objectAnimator = ObjectAnimator.ofFloat(view,View.ALPHA,*values)//"alpha" 它会调用setAlpha
            }
            ObjectAnimatorType.SCALEX -> {
                if(values.isEmpty()){
                    throw Exception("values不能为null")
                }
                objectAnimator = ObjectAnimator.ofFloat(view,View.SCALE_X,*values)//"scaleX" 它会调用setScaleX
            }
            ObjectAnimatorType.SCALEY -> {
                if(values.isEmpty()){
                    throw Exception("values不能为null")
                }
                objectAnimator = ObjectAnimator.ofFloat(view,View.SCALE_Y,*values)//"scaleY" 它会调用setScaleY
            }
            ObjectAnimatorType.TRANSLATIONX -> {
                if(values.isEmpty()){
                    throw Exception("values不能为null")
                }
                objectAnimator = ObjectAnimator.ofFloat(view,View.TRANSLATION_X,*values)// translationX 它会调用setTranslationX
            }
            ObjectAnimatorType.TRANSLATIONY -> {
                if(values.isEmpty()){
                    throw Exception("values不能为null")
                }
                objectAnimator = ObjectAnimator.ofFloat(view,View.TRANSLATION_Y,*values)// translationY 它会调用setTranslationY
            }
            ObjectAnimatorType.CUSTOMPROPERTY -> {
                if(customProperty.isNullOrEmpty() || values.isEmpty()){
                    throw Exception("customProperty与values不能为null")
                }
                objectAnimator = ObjectAnimator.ofFloat(view,customProperty,*values)
            }
            ObjectAnimatorType.XML -> {
                if(animXmlResId==null || animXmlResId <= 0){
                    throw Exception("请设置animXmlResId")
                }
                objectAnimator = animXmlResId?.let {
                    AnimatorInflater.loadAnimator(view?.context,
                        it
                    )
                } as ObjectAnimator
                objectAnimator.target = view
            }
            else -> {}
        }
        if(objectAnimator!=null){
            if (mOnObjectAnimatorAttributeListener != null) {
                mOnObjectAnimatorAttributeListener(objectAnimator)
            }
            objectAnimator.addUpdateListener {
                if (mAddUpdateListener != null) {
                    mAddUpdateListener(it)
                }
            }
        }

        return objectAnimator
    }


    /**
     *  组合动画
     *  @param view 动画控件
     * @param animator 动画数组对象
     * @param mOnAnimatorAttributeListener 动画属性设置监听
     * @param mOnAnimationEnd 动画结束监听
     */
    public fun animatorSet(view:View?,mOnAnimatorAttributeListener: ((animatorSet: AnimatorSet) -> Unit)?,mOnAnimationEnd:((animator:Animator)->Unit)?,vararg animator: ValueAnimator?){
        val animatorSet = AnimatorSet()
        animatorSet.playTogether(*animator)
        animatorSet.setTarget(view)
        if (mOnAnimatorAttributeListener != null) {
            mOnAnimatorAttributeListener(animatorSet)
        }
        animatorSet.addListener {
            if (mOnAnimationEnd != null) {
                mOnAnimationEnd(it)
            }
        }
        animatorSet.start()
    }

    /**
     *  组合动画
     *  @param view 动画控件
     * @param animator 动画数组对象
     * @param mOnAnimatorAttributeListener 动画属性设置监听
     * @param mOnAnimationEnd 动画结束监听
     */
    public fun animatorSetForNotStart(view:View?,mOnAnimatorAttributeListener: ((animatorSet: AnimatorSet) -> Unit)?,mOnAnimationEnd:((animator:Animator)->Unit)?,vararg animator: ValueAnimator?): AnimatorSet {
        val animatorSet = AnimatorSet()
        var play: AnimatorSet.Builder ?= null
        animator.forEachIndexed { index, animator ->
            if(index==0){
                play = animatorSet.play(animator)
            }else{
                play?.with(animator)
            }
        }
        animatorSet.setTarget(view)
        if(animatorSet!=null){
            if (mOnAnimatorAttributeListener != null) {
                mOnAnimatorAttributeListener(animatorSet)
            }
        }
        animatorSet.addListener {
            if (mOnAnimationEnd != null) {
                mOnAnimationEnd(it)
            }
        }
        return animatorSet
    }



    /**
     *  设置anim xml 中的动画
     * @param view 需要动画的控件
     * @param animXmlResId 动画xml id
     * @param mOnAnimatorAttributeListener 动画属性设置
     */
    public fun animatorSetForXML(view:View?,animXmlResId:Int = 0, mOnAnimatorAttributeListener: ((animatorSet: AnimatorSet) -> Unit)?){
        val animatorSet = AnimatorInflater.loadAnimator(view?.context,animXmlResId) as AnimatorSet
        animatorSet.setTarget(view)
        if(animatorSet!=null){
            if (mOnAnimatorAttributeListener != null) {
                mOnAnimatorAttributeListener(animatorSet)
            }
        }
        animatorSet.start()
    }


    /**
     * 属性动画
     * @sample
     * @author Icez
     * @param view 动画控件
     * @param type 属性动画类型
     * @param evaluator 动画计算
     * @param mOnValueAnimatorAttributeListener 属性设置
     * @param mAddUpdateListener 动画监听
     * @param values 动画值
     */
    public fun <T> valueAnimator(
        view:View?,
        type:ValueAnimatorType,
        evaluator:TypeEvaluator<T>?,
        mOnValueAnimatorAttributeListener: ((mValueAnimator: ValueAnimator?) -> Unit)?,
        mAddUpdateListener: ((valueAnimator: ValueAnimator) -> Unit)?,
        vararg values:T
    ): ValueAnimator? {
        var valueAnimator:ValueAnimator ?= null
        when(type){
            ValueAnimatorType.OBJECT ->{
                valueAnimator = ValueAnimator.ofObject(evaluator, *values)
            }
            ValueAnimatorType.FLOAT ->{
                valueAnimator = ValueAnimator.ofFloat(*values as FloatArray)
                valueAnimator.setEvaluator(evaluator)
            }
            ValueAnimatorType.ARGB ->{
                valueAnimator = ValueAnimator.ofArgb(*values as IntArray)
                valueAnimator.setEvaluator(evaluator)
            }
            ValueAnimatorType.INT ->{
                valueAnimator = ValueAnimator.ofArgb(*values as IntArray)
                valueAnimator.setEvaluator(evaluator)
            }
            else ->Unit
        }

        valueAnimator?.addUpdateListener {
            if (mAddUpdateListener != null) {
                mAddUpdateListener(it)
            }
        }
        valueAnimator?.setTarget(view)
        if (mOnValueAnimatorAttributeListener != null) {
            mOnValueAnimatorAttributeListener(valueAnimator)
        }
        return valueAnimator
    }

    enum class ValueAnimatorType{
        OBJECT,
        INT,
        FLOAT,
        ARGB,
    }

    /**
     *  动画类型枚举
     */
    enum class ObjectAnimatorType{
        ROTATION,
        SCALEX,
        SCALEY,
        TRANSLATIONX,
        TRANSLATIONY,
        ALPHA,
        XML,
        CUSTOMPROPERTY
    }
}